﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections;

namespace PQ.Util
{
    public class USB1612M
    {
        
        //函数功能：打开设备
        //参数：dev_num，如果计算机只插了一块卡，则该参数填0
        //返回值：如果函数调用成功，则返回非0值，调用失败，返回NULL
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern int USB1612M_OpenDevice(int dev_num);

        //函数功能：打开物理设备(此函数功能和USB1612M_OpenDevice函数相同，用户可二选一)
        //参数：无
        //返回值：如果函数调用成功，则返回非0值，调用失败，返回NULL
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern int USB1612M_OpenDeviceID();

        //功能：往USB总控芯片发送命令控制字
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //		request：	请求命令(0xB3)
        //			B3命令含义：USB总控芯片完成初始化
        //value:    值(填0x0)
        //len:		长度（填0x0）
        //buffer:	指针（填NULL）
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB_VENDOR_OR_CLASS_REQUEST(int husb, byte request, short value, int len, IntPtr buffer);
        //BOOL WINAPI USB_VENDOR_OR_CLASS_REQUEST(HANDLE husb,BYTE request,WORD value,int len,BYTE *buffer);

        //功能：往USB总控芯片发送请求命令
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //		request：	请求命令(0xB2、0xBA)
        //			B2命令含义：USB总控芯片允许传输
        //			BA命令含义：USB总控芯片禁止传输
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB1612M_IOCTL_VENDOR_REQUEST(int hDevice, byte request);
        //BOOL WINAPI USB1612M_IOCTL_VENDOR_REQUEST(HANDLE hDevice,BYTE request);

        //功能：从USB块读数据
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //		Buffer：	用来接收读取的数据
        //		BufferSize	需要读取的字节数
        //		nBytes		指针，指向实际读取的字节数
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB1612M_IOCTL_BULK_READ(int hDevice,  byte[] Buffer, uint BufferSize, ref uint nBytes);
        //bool WINAPI USB1612M_IOCTL_BULK_READ(HANDLE hDevice,void * Buffer,unsigned long BufferSize,unsigned long * nBytes);

        //功能：设置AD采样频率
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //		FreSelect：	取值范围（1-7）
        //		FreSelect取值与采样频率的对应关系如下：
        //		FreSelect取值	采样频率
        //			1			200KHz
        //			2			100KHz
        //			3			50KHz
        //			4			25KHz
        //			5			20KHz
        //			6			10KHz
        //			7			5KHz
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB1612M_SetADFre(int hDevice, byte FreSelect);

        //功能：设置AD触发模式
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //		ADMode：	取值范围（0-1）
        //		ADMode取值与触发方式的对应关系如下：
        //		ADMode取值	触发方式
        //		0			外触发
        //		1			软启动
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB1612M_SetADMode(int hDevice, byte ADMode);

        //功能：设置AD同步通道数
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //		ChSelect：取值范围（1-3）
        //		ChSelect取值与同步通道数的对应关系如下：
        //		ChSelect取值	同步通道数
        //			1			4通道同步
        //			2			8通道同步
        //			3			12通道同步
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB1612M_SetADCh(int hDevice, byte ChSelect);

        //功能：清空硬FIFO（硬FIFO指IDT7207）
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB1612M_CLRFIFO(int hDevice);

        //功能：复位AD
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE 
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB1612M_ADReset(int hDevice);

        //功能：软启动AD（如果为外触发模式，则还需要外触发信号的配合，详见《触发模式》章节）
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB1612M_ADStart(int hDevice);

        //功能：停止AD
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB1612M_ADStop(int hDevice);

        //功能：初始化AD，包含复位AD，启动AD（因为要完成AD复位，需配合一次启动），停止AD，清FIFO
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //返回值：无
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern void USB1612M_ADInit(int hDevice);

        //函数功能：微秒延时函数
        //参数：dly，微秒数
        //返回值：无
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern void  DelayUs(int dly);	

        //函数功能：关闭设备
        //参数：hDevice，设备操作句柄，由USB1612M_OpenDevice函数返回
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern bool USB1612M_CloseDevice(int hDevice);

        [DllImport("USB1612M.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
        public static extern double    xc_GetVersion( );  // 获得DLL版本号,返回版本号

        //保存句柄
        int hDevice;

        //设备ID
        int dev_num = 0;

        //设置频率的静态常量
        public static byte Fre200KHz = 1; //9216    36
        public static byte Fre100KHz = 2; //4608    18
        public static byte Fre50KHz = 3; // 4096    9
        public static byte Fre25KHz = 4; // 4096 8  
        public static byte Fre20KHz = 5; //4096  8         
        public static byte Fre10KHz = 6;//2048  4
        public static byte Fre5KHz = 7;//1024   2

        //设置通道的静态常量
        public static byte CH4 = 1;
        public static byte CH8 = 2;
        public static byte CH12 = 3;

        // 触发方式静态常量
        public static byte SoftwareTrigger = 1;//软启动
        public static byte OuterTrigger = 0;  //外触发

        //量程静态常量
        public static double Range5V = 5.0;
        public static double Range10V = 10.0;

        public DateTime startDateTime;



        //当前量程
  

        byte chSel;
        byte triggerMode;
        byte sampleFreq;

        public static ArrayList sampleFreqArr = new ArrayList();

        Configuration cfg;

        public  static USB1612M usb1612m ;

        bool readFlag = true;
        public static byte genSampleFreqIndex(string sampleF)
        {
            if (sampleFreqArr.Count == 0)
            {
                sampleFreqArr.Add(" ");
                sampleFreqArr.Add("200KHz");
                sampleFreqArr.Add("100KHz");
                sampleFreqArr.Add("50KHz");
                sampleFreqArr.Add("25KHz");
                sampleFreqArr.Add("20KHz");
                sampleFreqArr.Add("10KHz");
                sampleFreqArr.Add("5KHz");
            }

            return (byte)sampleFreqArr.IndexOf(sampleF);
        }
        public USB1612M()
        {

            sampleFreqArr.Add(" ");
            sampleFreqArr.Add("200KHz");
            sampleFreqArr.Add("100KHz");
            sampleFreqArr.Add("50KHz");
            sampleFreqArr.Add("25KHz");
            sampleFreqArr.Add("20KHz");
            sampleFreqArr.Add("10KHz");
            sampleFreqArr.Add("5KHz");
        }
        public static USB1612M getUSB1612M(Configuration cfg)
        {
            usb1612m = new USB1612M();
            usb1612m.setConfiguration(cfg);
            return usb1612m;
        }
        public static USB1612M getUSB1612M()
        {
            return usb1612m;
        }
  
        public void StartSample()
        {
        
            StartSample(chSel, sampleFreq, triggerMode);
            Read();

        }
      

        //
        public void Read()
        {
            uint nBytes = 0;
            //参数
            byte[] AD_Data;


            uint bufferSize=4096;
            int pn = 0;
            switch (sampleFreq)
            {
                case 1:
                    pn = 40000;
                    bufferSize = 9216;
                    break;
                case 2:
                    pn = 20000;
                    bufferSize = 4608;
                    break;
                case 3:
                    pn = 10000;
                    bufferSize = 4096;
                    break;
                case 4:
                    pn = 5000;
                    bufferSize = 4096;
                    break;
                case 5:
                    pn = 4000;
                    bufferSize = 4096;
                    break;
                case 6:
                    pn = 2000;
                    bufferSize = 2048;
                    break;
                case 7:
                    pn = 1000;
                    bufferSize = 1024;
                    break;
            }
            int totalSize = pn * 8 * chSel;
            byte[] totalAD_Data = new byte[totalSize];
            AD_Data = new byte[bufferSize];
            uint count = 0;
            while (readFlag)
            {
                USB1612M_IOCTL_BULK_READ(hDevice, AD_Data, bufferSize, ref nBytes);
                if (count + nBytes < totalSize)
                {
                    Array.Copy(AD_Data, 0, totalAD_Data, count, nBytes);
                    count += nBytes;
                }
                else
                {
                    Array.Copy(AD_Data, 0, totalAD_Data, count, totalSize - count);
                    cfg.dataExchange.Add(new DataValue(totalAD_Data, cfg));
                    totalAD_Data = new byte[totalSize];
                    Array.Copy(AD_Data, totalSize - count, totalAD_Data, 0, nBytes - totalSize + count);
                    count = nBytes - (uint)totalSize + count;
                    //Console.WriteLine(DateTime.Now + " : " + DateTime.Now.Millisecond);
                }


            }


        }
        //开始采样
        public void StartSample(byte ChSel, byte FreSel, byte ADMode)
        {
            IntPtr a = new IntPtr(0);
            USB_VENDOR_OR_CLASS_REQUEST(hDevice, 0xb3, 0x00, 0, a);
            //清空FIFO
            USB1612M_CLRFIFO(hDevice);

            //设置同步通道
            USB1612M_SetADCh(hDevice, ChSel);
            //设置采样频率
            USB1612M_SetADFre(hDevice, FreSel);
            //设置工作模式
            USB1612M_SetADMode(hDevice, ADMode);


            //允许传输
            USB1612M_IOCTL_VENDOR_REQUEST(hDevice, 0xB2);

            //启动AD
            USB1612M_ADStart(hDevice);

            startDateTime = DateTime.Now;
           


        }
        //从USB块读数据
        public bool Read(byte[] Buffer, uint BufferSize, ref uint nBytes)
        {
            return USB1612M_IOCTL_BULK_READ(hDevice, Buffer, BufferSize, ref nBytes);
        }
        public void StopSample()
        {
            readFlag = false;
            System.Threading.Thread.Sleep(100);
            USB1612M_IOCTL_VENDOR_REQUEST(hDevice, 0xBA);
            USB1612M_ADStop(hDevice);
            USB1612M_CLRFIFO(hDevice);
            

        }
        public void setConfiguration (Configuration cfg)
        {

            this.cfg = cfg;
            dev_num = cfg.dev_num;
            chSel = cfg.ch_sel;
            triggerMode = cfg.triggerMode;
            sampleFreq = (byte)sampleFreqArr.IndexOf(cfg.sampleFreqStr);

        }

        //打开装置
        public bool OpenDevice()
        {
           hDevice =  USB1612M_OpenDevice(dev_num);
           if (hDevice != 0)
           {
               //如果打开成功，则初始化
               USB1612M_ADInit(hDevice);
               return true;
           }
           else
               return false;
        }

        //设置采样率
        public bool SetADFre(byte FreSelect)
        {
            return USB1612M_SetADFre(hDevice,FreSelect);
        }

        //设置同步通道数
        public bool SetADCh(byte ChSelect)
        {
            return USB1612M_SetADCh(hDevice,ChSelect);
        }

        //设置触发方式
        public bool SetADMode(byte ADMode)
        {
          return USB1612M_SetADMode(hDevice,ADMode);
        }

       
        //功能：往USB总控芯片发送命令控制字
        //参数：hDevice:	卡的操作句柄，由USB1612M_OpenDevice函数返回
        //		request：	请求命令(0xB3)
        //			B3命令含义：USB总控芯片完成初始化
        //value:    值(填0x0)
        //len:		长度（填0x0）
        //buffer:	指针（填NULL）
        //返回值：如果函数调用成功，则返回TRUE，调用失败，返回FALSE
        public  bool VENDOR_OR_CLASS_REQUEST(byte request, short value, int len, IntPtr buffer)
        {
            return USB_VENDOR_OR_CLASS_REQUEST(hDevice, request, value, len,  buffer);
        }
        //功能：往USB总控芯片发送请求命令
        //		request：	请求命令(0xB2、0xBA)
        //			B2命令含义：USB总控芯片允许传输
        //			BA命令含义：USB总控芯片禁止传输
        public bool VendorRequest(byte request)
        {
            return USB1612M_IOCTL_VENDOR_REQUEST( hDevice,request);
        }
        //初始化AD
        public void ADInit()
        {
            USB1612M_ADInit(hDevice);
        }

        //软启动AD
        public bool ADStart()
        {
           
            bool b = USB1612M_ADStart(hDevice);
            startDateTime = DateTime.Now;
            return b;
        }

        //停止AD
        public bool ADStop()
        {
            return USB1612M_ADStop(hDevice);
        }

        //软启动AD
        public bool ADReset()
        {
            return USB1612M_ADReset(hDevice);
        }

        //清空硬FIFO
        public bool CLRFIFO()
        {
            return  USB1612M_CLRFIFO(hDevice);
        }

        //关闭装置
        public bool CloseDevice()
        {
           return  USB1612M_CloseDevice(hDevice);
        }

        //获取版本
        public double GetVersion()
        {
            return xc_GetVersion( );
        }

       

    }
}
